package com.yanyu.space.common.log;

import com.yanyu.space.common.core.bootlog.BootstrapLogContext;
import com.yanyu.space.common.core.properties.LogProperties;
import com.yanyu.space.common.log.handler.LogBootstrap;
import com.yanyu.space.common.log.support.LogMessageInterceptor;
import com.yanyu.space.common.log.support.LogWebFilter;
import com.yanyu.space.common.log.support.LogAsyncAspect;
import com.yanyu.space.common.log.support.LogXxljobAspect;
import com.yanyu.space.common.log.sender.kafka.KafkaLogSender;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.autoconfig.instrument.web.SleuthWebProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.config.GlobalChannelInterceptor;

import javax.servlet.DispatcherType;

/**
 * @author yanyu
 */
@Configuration
@ConditionalOnProperty(value = {"spring.sleuth.enabled", "space.log.enabled"}, matchIfMissing = true)
@EnableConfigurationProperties(value = LogProperties.class)
public class LogAutoConfig {

    @Autowired
    private Tracer tracer;
    private LogProperties logProperties;

    public LogAutoConfig(LogProperties logProperties) {
        this.logProperties = logProperties;
        BootstrapLogContext.put("log", String.format("开启分布式日志收集功能, 发送类型 -> kafka, 发送类型topic -> %s, " +
                "发送类型地址 -> %s", logProperties.getSender().getTopic(), logProperties.getSender().getServersAddr()));
    }

    @Bean
    public LogBootstrap logBootstrap() {
        return new LogBootstrap(logProperties);
    }

    @Bean
    public KafkaLogSender kafkaLogSender(LogProperties kafkaLogProperties) {
        return new KafkaLogSender(kafkaLogProperties);
    }

    @Bean
    @GlobalChannelInterceptor
    public LogMessageInterceptor logStreamInterceptor() {
        return new LogMessageInterceptor();
    }

    @Configuration
    @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
    @ConditionalOnProperty(value = "spring.sleuth.web.enabled", matchIfMissing = true)
    public class LogWebFilterConfig {
        @Autowired
        private SleuthWebProperties webProperties;
        @Autowired
        private LogProperties logProperties;

        @Bean
        public FilterRegistrationBean logTraceWebFilter() {
            FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new LogWebFilter(this.logProperties.getWeb().getExcludePatterns(), this.logProperties.getWeb().getIncludePatterns()));
            filterRegistrationBean.setDispatcherTypes(DispatcherType.ASYNC, DispatcherType.ERROR, DispatcherType.FORWARD,
                    DispatcherType.INCLUDE, DispatcherType.REQUEST);
            filterRegistrationBean.setOrder(this.webProperties.getFilterOrder() + 1);
            return filterRegistrationBean;
        }
    }

    @Configuration
    @ConditionalOnProperty(value = "spring.sleuth.async.enabled", matchIfMissing = true)
    public class LogTraceAsyncAspcectConfig {

        @Bean
        public LogAsyncAspect logTraceAsyncAspect() {
            return new LogAsyncAspect(tracer);
        }

        @Bean
        public LogXxljobAspect logTraceXxljobAspect() {
            return new LogXxljobAspect(tracer);
        }
    }
}
